﻿using System;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;
using WxLib.Core.Util;
using WxLib.Core.Serializers;
using WxLib.Core.RequestHandlers;
using WxLib.Common;
using WxLib.Business;

namespace WxLib.Business
{
    /// <summary>
    /// 用于企业向微信用户银行卡付款 接口实现
    /// </summary>
    public class PayToUser
    {
        private string defaultUri = "https://api.mch.weixin.qq.com";
        private readonly WxApiOptions options;

        public PayToUser(IOptions<WxApiOptions> optionsAccessor)
        {
            this.options = optionsAccessor.Value;
            BaseUri = new Uri(defaultUri);
            RequestHandler = new RequestHandler(new XmlSerializer());
        }


        /// <summary>
        /// 获取或设置用于执行请求的RequestHandler
        /// </summary>
        public IPostRequestHandler RequestHandler;

        /// <summary>
        /// 获取或设置请求的基本URI。
        /// </summary>
        public Uri BaseUri { get; set; }

        /// <summary>
        /// 用于企业向微信用户个人付款 
        /// </summary>
        /// <param name="partner_trade_no">店面订单号</param>
        /// <param name="openid">用户openid</param>
        /// <param name="check_name">是否校验用户姓名选项</param>
        /// <param name="re_user_name">收款用户姓名</param>
        /// <param name="amount">金额(RMB:分)</param>
        /// <param name="desc">企业付款描述信息</param>
        /// <param name="spbill_create_ip">调用接口的机器Ip地址</param>
        /// <returns></returns>
        public Task<PayToUserResponse> PayAsync(string partner_trade_no, string openid, bool check_name, string re_user_name, int amount, string desc, string spbill_create_ip)
        {
            var relUri = "/mmpaymkttransfers/promotion/transfers";
            PayToUserOptions  payToUserOptions = new PayToUserOptions();
            payToUserOptions.mch_appid = options.AppId;
            payToUserOptions.mchid = options.MchId;
            payToUserOptions.partner_trade_no = partner_trade_no;
            payToUserOptions.nonce_str = WxUtil.GetNoncestr();
            payToUserOptions.openid = openid;
            payToUserOptions.check_name = check_name ? "FORCE_CHECK" : "NO_CHECK";
            payToUserOptions.re_user_name = re_user_name;
            payToUserOptions.amount = amount;
            payToUserOptions.desc = desc;
            payToUserOptions.spbill_create_ip = spbill_create_ip;
            payToUserOptions.sign = WxUtil.GetSign<PayToUserOptions>(payToUserOptions, options.MchKey);
            var queryString = RequestHandler.Serializer.Serialize(payToUserOptions);
            return requestAsync<PayToUserResponse>(relUri, queryString);
        }

        /// <summary>
        /// 用于企业向微信用户个人付款 
        /// </summary>
        /// <param name="partner_trade_no">店面订单号</param>
        /// <param name="openid">用户openid</param>
        /// <param name="check_name">是否校验用户姓名选项</param>
        /// <param name="re_user_name">收款用户姓名</param>
        /// <param name="amount">金额(RMB:分)</param>
        /// <param name="desc">企业付款描述信息</param>
        /// <param name="spbill_create_ip">调用接口的机器Ip地址</param>
        /// <returns></returns>
        public PayToUserResponse Pay(string partner_trade_no, string openid, bool check_name, string re_user_name, int amount, string desc, string spbill_create_ip)
        {
            return PayAsync(partner_trade_no, openid, check_name, re_user_name, amount, desc, spbill_create_ip).Result;
        }

        /// <summary>
        /// 用于店面的企业付款操作进行结果查询，返回付款操作详细结果。
        /// </summary>
        /// <param name="partner_trade_no"></param>
        /// <returns></returns>
        public Task<QueryPayToUserResponse> QueryAsync(string partner_trade_no)
        {
            var relUri = "/mmpaymkttransfers/gettransferinfo";

            QueryPayToUserOptions queryPayToUserOptions = new QueryPayToUserOptions();
            queryPayToUserOptions.appid = options.AppId;
            queryPayToUserOptions.mch_id = options.MchId;
            queryPayToUserOptions.partner_trade_no = partner_trade_no;
            queryPayToUserOptions.nonce_str = WxUtil.GetNoncestr();
            queryPayToUserOptions.sign = WxUtil.GetSign<QueryPayToUserOptions>(queryPayToUserOptions, options.MchKey);
            var queryString = RequestHandler.Serializer.Serialize(queryPayToUserOptions);
            return requestAsync<QueryPayToUserResponse>(relUri, queryString);
        }

        /// <summary>
        /// 用于店面的企业付款操作进行结果查询，返回付款操作详细结果。
        /// </summary>
        /// <param name="partner_trade_no"></param>
        /// <returns></returns>
        public QueryPayToUserResponse Query(string partner_trade_no)
        {
            return QueryAsync(partner_trade_no).Result;
        }

        /// <summary>
        /// 异步请求 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="relUri"></param>
        /// <param name="queryString"></param>
        /// <returns></returns>
        private async Task<T> requestAsync<T>(string relUri, string queryString)
        {
            return await RequestHandler.PostRequestAsync<T>(new Uri(BaseUri, relUri),
                    queryString, options.CertPath, options.CertPassWord).ConfigureAwait(false);
        }
    }
}
